This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

source("tianfengRwrappers.R")
ds2 <- readRDS("ds2.rds")
selected_features <- read.csv("./datatable/ds2_features.csv", stringsAsFactors = F)
selected_features <- selected_features$Feature
Idents(ds2) <- ds2$seurat_clusters
ggobj <- multi_featureplot(selected_features[1:9], ds2, labels = NULL)
ggsave("ds2_features.png", device = png, height = 8, width = 8, plot = ggobj)

umap plot

ggsave("./fig2/ds2_ACumap.png", device = png, height = 4, width = 6, 
       plot = umapplot(ds2_AC, group.by = "Classification1", label.size = 5))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the
existing scale.
ggsave("./fig2/ds2_PAumap.png", device = png, height = 4, width = 6, 
       plot = umapplot(ds2_PA, group.by = "Classification1", label.size = 5))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the
existing scale.

Where is the Fibromyocyte

LUM

sep = 0.3
surfaceplot2("LUM",ds2,x_seq = seq(-2,13, sep), y_seq = seq(2,17,sep))

addmodulescore

geneset <- read.table("SMC")

ds2_AC <- AddModuleScore(ds2_AC,features = geneset, name = 'SMC_score')
ds2_PA <- AddModuleScore(ds2_PA,features = geneset, name = 'SMC_score')

(f("SMC_score1",label = F, ds2_AC) + scale_colour_gradient(low="#1E90FF", high="#ff2121")) %>%
  ggsave("./fig2/ds2_AC_SMCscore.png", device = png, height = 4, width = 5, plot = .)
(f("SMC_score1",label = F, ds2_PA) + scale_colour_gradient(low="#1E90FF", high="#ff2121")) %>%
  ggsave("./fig2/ds2_PA_SMCscore.png", device = png, height = 4, width = 5, plot = .)

# dataset1 <- AddModuleScore_UCell(dataset1,features = geneset, name = 'fibromyo_score')

geneset <- read.table("FB")

ds2_AC <- AddModuleScore(ds2_AC,features = geneset, name = 'FB_score')
ds2_PA <- AddModuleScore(ds2_PA,features = geneset, name = 'FB_score')

(f("FB_score1", label = F, ds2_AC) +scale_colour_gradient(low="#1E90FF", high="#ff2121")) %>%
  ggsave("./fig2/ds2_AC_FBscore.png", device = png, height = 4, width = 5, plot = .)
(f("FB_score1", label = F, ds2_PA) +scale_colour_gradient(low="#1E90FF", high="#ff2121")) %>%
  ggsave("./fig2/ds2_PA_FBscore.png", device = png, height = 4, width = 5, plot = .)

key features have gradient expression

BGN LUM

ridgetheme <- theme(plot.title = element_text(size = 15,color="black",hjust = 0.5),
                 axis.title = element_text(size = 15,color ="black"), 
                 axis.text = element_text(size = 15,color = "black"),
                 panel.grid.minor.y = element_blank(),
                 panel.grid.minor.x = element_blank(),
                 axis.text.x = element_text(angle = 0, hjust = 1),
                 panel.grid=element_blank(),
                 legend.position = "top",
                 legend.text = element_text(size= 15),
                 legend.title= element_text(size= 15)) 

ridge plot

df <- FetchData(ds2_AC,vars = c("FB_score1","SMC_score1","BGN","LUM","UMAP_1","UMAP_2"))
# df <- arrange(df,FB_score1,by_group = F)
data <- cbind(df,index = 1:nrow(df),cluster = Idents(ds2_AC))

(ggplot(data,aes(x=SMC_score1)) + geom_point(aes(y = BGN, color = cluster),alpha = 1) + geom_smooth(aes(y = BGN), color = "red") + theme_classic() + ridgetheme + scale_y_continuous(limits = c(1,5)) + scale_color_manual(values = colors_list) + theme(legend.key.size = unit(1,"cm")) + guides(colour = guide_legend(override.aes = list(size=10)))) 

(ggplot(data,aes(x=FB_score1)) + geom_point(aes(y = LUM, color = cluster),alpha = 1) + geom_smooth(aes(y = BGN), color = "green") + theme_classic() + ridgetheme +scale_y_continuous(limits = c(1,5)) + scale_color_manual(values = colors_list) + guides(colour = guide_legend(override.aes = list(size=10))))


df <- FetchData(ds2_PA,vars = c("FB_score1","SMC_score1","BGN","LUM","UMAP_1","UMAP_2"))
# df <- arrange(df,FB_score1,by_group = F)
data <- cbind(df,index = 1:nrow(df),cluster = Idents(ds2_PA))

ggplot(data,aes(x=SMC_score1)) + geom_point(aes(y = BGN, color = cluster),alpha = 1) + geom_smooth(aes(y = BGN), color = "red") + theme_classic() + ridgetheme + scale_y_continuous(limits = c(1,5)) + scale_color_manual(values = colors_list) + guides(colour = guide_legend(override.aes = list(size=10)))

ggplot(data,aes(x=FB_score1)) + geom_point(aes(y = LUM, color = cluster),alpha = 1) + geom_smooth(aes(y = BGN), color = "green") + theme_classic() + ridgetheme +scale_y_continuous(limits = c(1,5)) + scale_color_manual(values = colors_list) + guides(colour = guide_legend(override.aes = list(size=10)))

# ggplot(data,aes(x=FB_score1)) + geom_point(aes(y = BGN),color = "#e2b398",alpha = 1) + geom_smooth(aes(y = BGN), color = "red") + geom_point(aes(y=LUM),color = "#d1eba8",alpha = 1) + geom_smooth(aes(y = LUM), color = "green") + theme_classic() + ridgetheme +scale_y_continuous(limits = c(1,5))

fig.D

AC->PA

umapplot(ds2_PA,group.by = "ref_celltype", repel = T, label.size = 5) %>% 
  ggsave("./fig2/sup_ds2PA_umap2.png",plot = ., device = png, height = 4, width = 6)
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the
existing scale.

numerical umap

embedding <- FetchData(object = ds2_PA, vars = c("UMAP_1", "UMAP_2"))
embedding <- cbind(embedding, cbind(ds2_PA$X0,ds2_PA$X1,ds2_PA$X2,ds2_PA$X3))

ggobj <- ggplot() +
  geom_point(data = embedding[embedding$`1`>0.1,], 
             aes(x = UMAP_1, y = UMAP_2, color = `1`), shape=16, size = 3, alpha=0.5) + 
  scale_color_gradient('0', low = "#FFFFFF00", high = "#6dc0a6") +
  new_scale("color") +
    geom_point(data = embedding[embedding$`2`>0.1,], 
             aes(x = UMAP_1, y = UMAP_2, color = `2`),shape=16, size = 3, alpha=0.5) + 
  scale_color_gradient('1', low = "#FFFFFF00", high = "#e2b398") +
   new_scale("color") +
    geom_point(data = embedding[embedding$`3`>0.1,], 
             aes(x = UMAP_1, y = UMAP_2, color = `3`),shape=16, size = 3, alpha=0.5) + 
  scale_color_gradient('2', low = "#FFFFFF00", high = "#e2a2ca") +
  new_scale("color") +
    geom_point(data = embedding[embedding$`4`>0.1,], 
             aes(x = UMAP_1, y = UMAP_2, color = `4`),shape=16, size = 3, alpha=0.5) + 
  scale_color_gradient('3', low = "#FFFFFF00", high = "#d1eba8") +
        xlab("UMAP 1") + ylab("UMAP 2")  +
        theme(axis.line = element_line(arrow = arrow(length = unit(0.2, "cm")))) +
        scale_y_continuous(breaks = NULL) +
        scale_x_continuous(breaks = NULL) + 
  theme(panel.background = element_blank(), panel.grid = element_blank(), legend.position = "bottom")
ggsave("./fig2/sup_ds2PA_umap.png",device = png, plot = ggobj, height = 10,width = 10)

PA->AC

train on PA

numerical umap

ggsave("./fig2/sup_ds2AC_umap.png",device = png, plot = ggobj,height = 10,width = 10)
Error in FUN(X[[i]], ...) : 找不到对象'0'

GSVA

GSVAres <- readRDS("GSVAres.rds")
es <- data.frame(t(GSVAres),stringsAsFactors=F)  #可视化相关通路的在umap上聚集情况
ds2_AC <- AddMetaData(ds2_AC, es)
f("CUI_TCF21_TARGETS_UP", label = F, ds2_AC) +scale_colour_gradient(low="#1E90FF", high="#ff2121")

ds2_PA <- AddMetaData(ds2_PA, es)
f("CUI_TCF21_TARGETS_UP", label = F, ds2_PA) +scale_colour_gradient(low="#1E90FF", high="#ff2121")

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CnNvdXJjZSgidGlhbmZlbmdSd3JhcHBlcnMuUiIpCmRzMiA8LSByZWFkUkRTKCJkczIucmRzIikKc2VsZWN0ZWRfZmVhdHVyZXMgPC0gcmVhZC5jc3YoIi4vZGF0YXRhYmxlL2RzMl9mZWF0dXJlcy5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKc2VsZWN0ZWRfZmVhdHVyZXMgPC0gc2VsZWN0ZWRfZmVhdHVyZXMkRmVhdHVyZQpJZGVudHMoZHMyKSA8LSBkczIkc2V1cmF0X2NsdXN0ZXJzCmdnb2JqIDwtIG11bHRpX2ZlYXR1cmVwbG90KHNlbGVjdGVkX2ZlYXR1cmVzWzE6OV0sIGRzMiwgbGFiZWxzID0gTlVMTCkKZ2dzYXZlKCJkczJfZmVhdHVyZXMucG5nIiwgZGV2aWNlID0gcG5nLCBoZWlnaHQgPSA4LCB3aWR0aCA9IDgsIHBsb3QgPSBnZ29iaikKYGBgCgojIHVtYXAgcGxvdApgYGB7cn0KZ2dzYXZlKCIuL2ZpZzIvZHMyX0FDdW1hcC5wbmciLCBkZXZpY2UgPSBwbmcsIGhlaWdodCA9IDQsIHdpZHRoID0gNiwgCiAgICAgICBwbG90ID0gdW1hcHBsb3QoZHMyX0FDLCBncm91cC5ieSA9ICJDbGFzc2lmaWNhdGlvbjEiLCBsYWJlbC5zaXplID0gNSkpCmdnc2F2ZSgiLi9maWcyL2RzMl9QQXVtYXAucG5nIiwgZGV2aWNlID0gcG5nLCBoZWlnaHQgPSA0LCB3aWR0aCA9IDYsIAogICAgICAgcGxvdCA9IHVtYXBwbG90KGRzMl9QQSwgZ3JvdXAuYnkgPSAiQ2xhc3NpZmljYXRpb24xIiwgbGFiZWwuc2l6ZSA9IDUpKQpgYGAKCiMgV2hlcmUgaXMgdGhlIEZpYnJvbXlvY3l0ZQojIyMgTFVNCmBgYHtyfQpzZXAgPSAwLjMKc3VyZmFjZXBsb3QyKCJMVU0iLGRzMix4X3NlcSA9IHNlcSgtMiwxMywgc2VwKSwgeV9zZXEgPSBzZXEoMiwxNyxzZXApKQpgYGAKCiMjICBhZGRtb2R1bGVzY29yZQpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0zfQpnZW5lc2V0IDwtIHJlYWQudGFibGUoIlNNQyIpCgpkczJfQUMgPC0gQWRkTW9kdWxlU2NvcmUoZHMyX0FDLGZlYXR1cmVzID0gZ2VuZXNldCwgbmFtZSA9ICdTTUNfc2NvcmUnKQpkczJfUEEgPC0gQWRkTW9kdWxlU2NvcmUoZHMyX1BBLGZlYXR1cmVzID0gZ2VuZXNldCwgbmFtZSA9ICdTTUNfc2NvcmUnKQoKKGYoIlNNQ19zY29yZTEiLGxhYmVsID0gRiwgZHMyX0FDKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudChsb3c9IiMxRTkwRkYiLCBoaWdoPSIjZmYyMTIxIikpICU+JQogIGdnc2F2ZSgiLi9maWcyL2RzMl9BQ19TTUNzY29yZS5wbmciLCBkZXZpY2UgPSBwbmcsIGhlaWdodCA9IDQsIHdpZHRoID0gNSwgcGxvdCA9IC4pCihmKCJTTUNfc2NvcmUxIixsYWJlbCA9IEYsIGRzMl9QQSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93PSIjMUU5MEZGIiwgaGlnaD0iI2ZmMjEyMSIpKSAlPiUKICBnZ3NhdmUoIi4vZmlnMi9kczJfUEFfU01Dc2NvcmUucG5nIiwgZGV2aWNlID0gcG5nLCBoZWlnaHQgPSA0LCB3aWR0aCA9IDUsIHBsb3QgPSAuKQoKIyBkYXRhc2V0MSA8LSBBZGRNb2R1bGVTY29yZV9VQ2VsbChkYXRhc2V0MSxmZWF0dXJlcyA9IGdlbmVzZXQsIG5hbWUgPSAnZmlicm9teW9fc2NvcmUnKQoKZ2VuZXNldCA8LSByZWFkLnRhYmxlKCJGQiIpCgpkczJfQUMgPC0gQWRkTW9kdWxlU2NvcmUoZHMyX0FDLGZlYXR1cmVzID0gZ2VuZXNldCwgbmFtZSA9ICdGQl9zY29yZScpCmRzMl9QQSA8LSBBZGRNb2R1bGVTY29yZShkczJfUEEsZmVhdHVyZXMgPSBnZW5lc2V0LCBuYW1lID0gJ0ZCX3Njb3JlJykKCihmKCJGQl9zY29yZTEiLCBsYWJlbCA9IEYsIGRzMl9BQykgK3NjYWxlX2NvbG91cl9ncmFkaWVudChsb3c9IiMxRTkwRkYiLCBoaWdoPSIjZmYyMTIxIikpICU+JQogIGdnc2F2ZSgiLi9maWcyL2RzMl9BQ19GQnNjb3JlLnBuZyIsIGRldmljZSA9IHBuZywgaGVpZ2h0ID0gNCwgd2lkdGggPSA1LCBwbG90ID0gLikKKGYoIkZCX3Njb3JlMSIsIGxhYmVsID0gRiwgZHMyX1BBKSArc2NhbGVfY29sb3VyX2dyYWRpZW50KGxvdz0iIzFFOTBGRiIsIGhpZ2g9IiNmZjIxMjEiKSkgJT4lCiAgZ2dzYXZlKCIuL2ZpZzIvZHMyX1BBX0ZCc2NvcmUucG5nIiwgZGV2aWNlID0gcG5nLCBoZWlnaHQgPSA0LCB3aWR0aCA9IDUsIHBsb3QgPSAuKQpgYGAKCiMga2V5IGZlYXR1cmVzIGhhdmUgZ3JhZGllbnQgZXhwcmVzc2lvbgojIyBCR04gTFVNCmBgYHtyfQpyaWRnZXRoZW1lIDwtIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGNvbG9yPSJibGFjayIsaGp1c3QgPSAwLjUpLAogICAgICAgICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGNvbG9yID0iYmxhY2siKSwgCiAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxjb2xvciA9ICJibGFjayIpLAogICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDEpLAogICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9IDE1KSwKICAgICAgICAgICAgICAgICBsZWdlbmQudGl0bGU9IGVsZW1lbnRfdGV4dChzaXplPSAxNSkpIApgYGAKCiMjIHJpZGdlIHBsb3QKYGBge3J9CmRmIDwtIEZldGNoRGF0YShkczJfQUMsdmFycyA9IGMoIkZCX3Njb3JlMSIsIlNNQ19zY29yZTEiLCJCR04iLCJMVU0iLCJVTUFQXzEiLCJVTUFQXzIiKSkKIyBkZiA8LSBhcnJhbmdlKGRmLEZCX3Njb3JlMSxieV9ncm91cCA9IEYpCmRhdGEgPC0gY2JpbmQoZGYsaW5kZXggPSAxOm5yb3coZGYpLGNsdXN0ZXIgPSBJZGVudHMoZHMyX0FDKSkKCihnZ3Bsb3QoZGF0YSxhZXMoeD1TTUNfc2NvcmUxKSkgKyBnZW9tX3BvaW50KGFlcyh5ID0gQkdOLCBjb2xvciA9IGNsdXN0ZXIpLGFscGhhID0gMSkgKyBnZW9tX3Ntb290aChhZXMoeSA9IEJHTiksIGNvbG9yID0gInJlZCIpICsgdGhlbWVfY2xhc3NpYygpICsgcmlkZ2V0aGVtZSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDEsNSkpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yc19saXN0KSArIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMSwiY20iKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT0xMCkpKSkgCgooZ2dwbG90KGRhdGEsYWVzKHg9RkJfc2NvcmUxKSkgKyBnZW9tX3BvaW50KGFlcyh5ID0gTFVNLCBjb2xvciA9IGNsdXN0ZXIpLGFscGhhID0gMSkgKyBnZW9tX3Ntb290aChhZXMoeSA9IEJHTiksIGNvbG9yID0gImdyZWVuIikgKyB0aGVtZV9jbGFzc2ljKCkgKyByaWRnZXRoZW1lICtzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygxLDUpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfbGlzdCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT0xMCkpKSkKCgpkZiA8LSBGZXRjaERhdGEoZHMyX1BBLHZhcnMgPSBjKCJGQl9zY29yZTEiLCJTTUNfc2NvcmUxIiwiQkdOIiwiTFVNIiwiVU1BUF8xIiwiVU1BUF8yIikpCiMgZGYgPC0gYXJyYW5nZShkZixGQl9zY29yZTEsYnlfZ3JvdXAgPSBGKQpkYXRhIDwtIGNiaW5kKGRmLGluZGV4ID0gMTpucm93KGRmKSxjbHVzdGVyID0gSWRlbnRzKGRzMl9QQSkpCgpnZ3Bsb3QoZGF0YSxhZXMoeD1TTUNfc2NvcmUxKSkgKyBnZW9tX3BvaW50KGFlcyh5ID0gQkdOLCBjb2xvciA9IGNsdXN0ZXIpLGFscGhhID0gMSkgKyBnZW9tX3Ntb290aChhZXMoeSA9IEJHTiksIGNvbG9yID0gInJlZCIpICsgdGhlbWVfY2xhc3NpYygpICsgcmlkZ2V0aGVtZSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDEsNSkpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yc19saXN0KSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTEwKSkpCgpnZ3Bsb3QoZGF0YSxhZXMoeD1GQl9zY29yZTEpKSArIGdlb21fcG9pbnQoYWVzKHkgPSBMVU0sIGNvbG9yID0gY2x1c3RlciksYWxwaGEgPSAxKSArIGdlb21fc21vb3RoKGFlcyh5ID0gQkdOKSwgY29sb3IgPSAiZ3JlZW4iKSArIHRoZW1lX2NsYXNzaWMoKSArIHJpZGdldGhlbWUgK3NjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDEsNSkpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yc19saXN0KSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTEwKSkpCgojIGdncGxvdChkYXRhLGFlcyh4PUZCX3Njb3JlMSkpICsgZ2VvbV9wb2ludChhZXMoeSA9IEJHTiksY29sb3IgPSAiI2UyYjM5OCIsYWxwaGEgPSAxKSArIGdlb21fc21vb3RoKGFlcyh5ID0gQkdOKSwgY29sb3IgPSAicmVkIikgKyBnZW9tX3BvaW50KGFlcyh5PUxVTSksY29sb3IgPSAiI2QxZWJhOCIsYWxwaGEgPSAxKSArIGdlb21fc21vb3RoKGFlcyh5ID0gTFVNKSwgY29sb3IgPSAiZ3JlZW4iKSArIHRoZW1lX2NsYXNzaWMoKSArIHJpZGdldGhlbWUgK3NjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDEsNSkpCgpgYGAKCi0tLQoKIyBmaWcuRAojIyBBQy0+UEEKYGBge3J9CnNvdXJjZSgiWEdCb29zdF93cmFwcGVyLlIiKQpzb3VyY2UoInRpYW5mZW5nUndyYXBwZXJzLlIiKQoKSWRlbnRzKGRzMl9BQykgPC0gZmFjdG9yKElkZW50cyhkczJfQUMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkZpYnJvYmxhc3QiLCJGaWJyb215b2N5dGUiLCJQZXJpY3l0ZSIsIlNNQzEiLCJTTUMyIiwiVW5hc3NpZ25lZCIpKQoKYnN0X21vZGVsIDwtIFhHQm9vc3RfdHJhaW5fZnJvbV9zZXVvYmooZHMyX0FDKQpkczJfUEEgPC0gWEdCb29zdF9wcmVkaWN0X2Zyb21fc2V1b2JqKGRzMl9QQSxic3RfbW9kZWwpCgpjb25mdXNlX21hdCA8LSBYR0Jvb3N0X3ByZWRpY3RfZnJvbV9zZXVvYmooZHMyX1BBLCBic3RfbW9kZWwsIHJldHVybl9jb25mdXNlX21hdHJpeCA9IFQpCiMgc2Fua2V5X3Bsb3QoY29uZnVzZV9tYXQsc2Vzc2lvbiA9ICJBQyAtPiBQQSIpCmRzMl9QQSA8LSBwcm9qZWN0MnJlZl9jZWxsdHlwZTIoZHMyX1BBLCBkczJfQUMpCgpkczJfUEEkcmVmX2NlbGx0eXBlIDwtIGZhY3RvcihkczJfUEEkcmVmX2NlbGx0eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJGaWJyb2JsYXN0IiwiRmlicm9teW9jeXRlIiwiUGVyaWN5dGUiLCJTTUMxIiwiU01DMiIsIlVuYXNzaWduZWQiKSkKCnVtYXBwbG90KGRzMl9QQSxncm91cC5ieSA9ICJyZWZfY2VsbHR5cGUiLCByZXBlbCA9IFQsIGxhYmVsLnNpemUgPSA1KSAlPiUgCiAgZ2dzYXZlKCIuL2ZpZzIvc3VwX2RzMlBBX3VtYXAyLnBuZyIscGxvdCA9IC4sIGRldmljZSA9IHBuZywgaGVpZ2h0ID0gNCwgd2lkdGggPSA2KQoKY29uZnVzZV9tYXQgPC0gWEdCb29zdF9wcmVkaWN0X2Zyb21fc2V1b2JqKGRzMl9QQSwgYnN0X21vZGVsLCByZXR1cm5fY29uZnVzZV9tYXRyaXggPSBUKQoKbGFiZWwxID0gZGltbmFtZXMoY29uZnVzZV9tYXQpJHByZQpsYWJlbDIgPSBkaW1uYW1lcyhjb25mdXNlX21hdCkkdHJ1ZQoKc291cmNlcyA8LSByZXAoMDoobGVuZ3RoKGxhYmVsMSkgLSAxKSwgZWFjaCA9IGxlbmd0aChsYWJlbDIpKSAjIOazqOaEj+i/memHjOeahGVhY2jlkox0aW1lc+eahOWMuuWIqwpjb2xvcnMgPC0gcmVwKGFlcm9fY29sb3JzX2xpc3RbMSwyLDMsNV0sIGVhY2ggPSBsZW5ndGgobGFiZWwyKSkKdGFyZ2V0cyA8LSByZXAobGVuZ3RoKGxhYmVsMSkgKyAwOihsZW5ndGgobGFiZWwyKSAtIDEpLCB0aW1lcyA9IGxlbmd0aChsYWJlbDEpKQoKcGxvdF9seSgKICAgIHR5cGUgPSAic2Fua2V5Iiwgb3JpZW50YXRpb24gPSAiaCIsCiAgICBub2RlID0gbGlzdCgKICAgICAgICBsYWJlbCA9IE5VTEwsCiAgICAgICAgY29sb3IgPSBjKGNvbG9yc19saXN0WzEsMiwzLDVdLCBjb2xvcnNfbGlzdFtjKDE6Myw1KV0pLCBwYWQgPSAxNSwgdGhpY2tuZXNzID0gMzAsCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCB3aWR0aCA9IDEpCiAgICApLAogICAgbGluayA9IGxpc3QoCiAgICAgICAgc291cmNlID0gc291cmNlcywgdGFyZ2V0ID0gdGFyZ2V0cywKICAgICAgICB2YWx1ZSA9IGFzLm51bWVyaWMoY29uZnVzZV9tYXQpLAogICAgICAgIGNvbG9yID0gY29sb3JzCiAgICApCikgJT4lIGxheW91dCh0aXRsZSA9ICJBQyAtPiBQQSIsIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJBcmlhbCIsIHNpemUgPSAyMCwgY29sb3IgPSAiYmxhY2siKSkKCmBgYAojIyMgbnVtZXJpY2FsIHVtYXAKYGBge3J9CmVtYmVkZGluZyA8LSBGZXRjaERhdGEob2JqZWN0ID0gZHMyX1BBLCB2YXJzID0gYygiVU1BUF8xIiwgIlVNQVBfMiIpKQplbWJlZGRpbmcgPC0gY2JpbmQoZW1iZWRkaW5nLCBjYmluZChkczJfUEEkWDAsZHMyX1BBJFgxLGRzMl9QQSRYMixkczJfUEEkWDMpKQoKZ2dvYmogPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGVtYmVkZGluZ1tlbWJlZGRpbmckYDFgPjAuMSxdLCAKICAgICAgICAgICAgIGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yLCBjb2xvciA9IGAxYCksIHNoYXBlPTE2LCBzaXplID0gMywgYWxwaGE9MC41KSArIAogIHNjYWxlX2NvbG9yX2dyYWRpZW50KCcwJywgbG93ID0gIiNGRkZGRkYwMCIsIGhpZ2ggPSAiIzZkYzBhNiIpICsKICBuZXdfc2NhbGUoImNvbG9yIikgKwogICAgZ2VvbV9wb2ludChkYXRhID0gZW1iZWRkaW5nW2VtYmVkZGluZyRgMmA+MC4xLF0sIAogICAgICAgICAgICAgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIsIGNvbG9yID0gYDJgKSxzaGFwZT0xNiwgc2l6ZSA9IDMsIGFscGhhPTAuNSkgKyAKICBzY2FsZV9jb2xvcl9ncmFkaWVudCgnMScsIGxvdyA9ICIjRkZGRkZGMDAiLCBoaWdoID0gIiNlMmIzOTgiKSArCiAgIG5ld19zY2FsZSgiY29sb3IiKSArCiAgICBnZW9tX3BvaW50KGRhdGEgPSBlbWJlZGRpbmdbZW1iZWRkaW5nJGAzYD4wLjEsXSwgCiAgICAgICAgICAgICBhZXMoeCA9IFVNQVBfMSwgeSA9IFVNQVBfMiwgY29sb3IgPSBgM2ApLHNoYXBlPTE2LCBzaXplID0gMywgYWxwaGE9MC41KSArIAogIHNjYWxlX2NvbG9yX2dyYWRpZW50KCcyJywgbG93ID0gIiNGRkZGRkYwMCIsIGhpZ2ggPSAiI2UyYTJjYSIpICsKICBuZXdfc2NhbGUoImNvbG9yIikgKwogICAgZ2VvbV9wb2ludChkYXRhID0gZW1iZWRkaW5nW2VtYmVkZGluZyRgNGA+MC4xLF0sIAogICAgICAgICAgICAgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIsIGNvbG9yID0gYDRgKSxzaGFwZT0xNiwgc2l6ZSA9IDMsIGFscGhhPTAuNSkgKyAKICBzY2FsZV9jb2xvcl9ncmFkaWVudCgnMycsIGxvdyA9ICIjRkZGRkZGMDAiLCBoaWdoID0gIiNkMWViYTgiKSArCiAgICAgICAgeGxhYigiVU1BUCAxIikgKyB5bGFiKCJVTUFQIDIiKSAgKwogICAgICAgIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC4yLCAiY20iKSkpKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpICsKICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgKyAKICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKZ2dzYXZlKCIuL2ZpZzIvc3VwX2RzMlBBX3VtYXAucG5nIixkZXZpY2UgPSBwbmcsIHBsb3QgPSBnZ29iaiwgaGVpZ2h0ID0gMTAsd2lkdGggPSAxMCkKYGBgCgoKIyMgUEEtPkFDCiMjIyB0cmFpbiBvbiBQQQpgYGB7cn0KSWRlbnRzKGRzMl9QQSkgPC0gZmFjdG9yKElkZW50cyhkczJfUEEpLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkZpYnJvYmxhc3QiLCJGaWJyb215b2N5dGUiLCJQZXJpY3l0ZSIsIlNNQzEiLCJTTUMyIiwiVW5hc3NpZ25lZCIpKQoKYnN0X21vZGVsIDwtIFhHQm9vc3RfdHJhaW5fZnJvbV9zZXVvYmooZHMyX1BBKQpkczJfQUMgPC0gWEdCb29zdF9wcmVkaWN0X2Zyb21fc2V1b2JqKGRzMl9BQyxic3RfbW9kZWwpCnVtYXBwbG90KGRzMl9BQyxncm91cC5ieSA9ICJwcm9qZWN0ZWRfaWRlbnRzIikKZHMyX0FDIDwtIHByb2plY3QycmVmX2NlbGx0eXBlMihkczJfQUMsZHMyX1BBKQoKZHMyX0FDJHJlZl9jZWxsdHlwZSA8LSBmYWN0b3IoZHMyX0FDJHJlZl9jZWxsdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRmlicm9ibGFzdCIsIkZpYnJvbXlvY3l0ZSIsIlBlcmljeXRlIiwiU01DMSIsIlNNQzIiLCJVbmFzc2lnbmVkIikpCgp1bWFwcGxvdChkczJfQUMsZ3JvdXAuYnkgPSAicmVmX2NlbGx0eXBlIiwgcmVwZWwgPSBULCBsYWJlbC5zaXplID0gNSkgICU+JSAKICBnZ3NhdmUoIi4vZmlnMi9zdXBfZHMyQUNfdW1hcDIucG5nIixwbG90ID0gLiwgZGV2aWNlID0gcG5nLCBoZWlnaHQgPSA0LCB3aWR0aCA9IDYpCgpjb25mdXNlX21hdCA8LSBYR0Jvb3N0X3ByZWRpY3RfZnJvbV9zZXVvYmooZHMyX0FDLCBic3RfbW9kZWwsIHJldHVybl9jb25mdXNlX21hdHJpeCA9IFQpCiMgc2Fua2V5X3Bsb3QoY29uZnVzZV9tYXQsc2Vzc2lvbiA9ICJQQSAtPiBBQyIpCgpsYWJlbDEgPSBkaW1uYW1lcyhjb25mdXNlX21hdCkkcHJlCmxhYmVsMiA9IGRpbW5hbWVzKGNvbmZ1c2VfbWF0KSR0cnVlCmNvbmZ1c2VfbWF0CnNvdXJjZXMgPC0gcmVwKDA6KGxlbmd0aChsYWJlbDEpIC0gMSksIGVhY2ggPSBsZW5ndGgobGFiZWwyKSkgIyDms6jmhI/ov5nph4znmoRlYWNo5ZKMdGltZXPnmoTljLrliKsKY29sb3JzIDwtIHJlcChhZXJvX2NvbG9yc19saXN0WzI6Nl0sIGVhY2ggPSBsZW5ndGgobGFiZWwyKSkKdGFyZ2V0cyA8LSByZXAobGVuZ3RoKGxhYmVsMSkgKyAwOihsZW5ndGgobGFiZWwyKSAtIDEpLCB0aW1lcyA9IGxlbmd0aChsYWJlbDEpKQoKcGxvdF9seSgKICAgIHR5cGUgPSAic2Fua2V5Iiwgb3JpZW50YXRpb24gPSAiaCIsCiAgICBub2RlID0gbGlzdCgKICAgICAgICBsYWJlbCA9IE5VTEwsCiAgICAgICAgY29sb3IgPSBjKGNvbG9yc19saXN0WzI6Nl0sIGNvbG9yc19saXN0W2MoMTozLDUpXSksIHBhZCA9IDE1LCB0aGlja25lc3MgPSAzMCwKICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICJibGFjayIsIHdpZHRoID0gMSkKICAgICksCiAgICBsaW5rID0gbGlzdCgKICAgICAgICBzb3VyY2UgPSBzb3VyY2VzLCB0YXJnZXQgPSB0YXJnZXRzLAogICAgICAgIHZhbHVlID0gYXMubnVtZXJpYyhjb25mdXNlX21hdCksCiAgICAgICAgY29sb3IgPSBjb2xvcnMKICAgICkKKSAlPiUgbGF5b3V0KHRpdGxlID0gIlBBIC0+IEFDIiwgZm9udCA9IGxpc3QoZmFtaWx5ID0gIkFyaWFsIiwgc2l6ZSA9IDIwLCBjb2xvciA9ICJibGFjayIpKQpgYGAKIyMjIG51bWVyaWNhbCB1bWFwCmBgYHtyfQplbWJlZGRpbmcgPC0gRmV0Y2hEYXRhKG9iamVjdCA9IGRzMl9BQywgdmFycyA9IGMoIlVNQVBfMSIsICJVTUFQXzIiKSkKZW1iZWRkaW5nIDwtIGNiaW5kKGVtYmVkZGluZywgY2JpbmQoZHMyX0FDJFgwLGRzMl9BQyRYMSxkczJfQUMkWDIsZHMyX0FDJFgzKSkKCmdnb2JqIDwtIGdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBlbWJlZGRpbmdbZW1iZWRkaW5nJGAxYD4wLjEsXSwgCiAgICAgICAgICAgICBhZXMoeCA9IFVNQVBfMSwgeSA9IFVNQVBfMiwgY29sb3IgPSBgMWApLCBzaGFwZT0xNiwgc2l6ZSA9IDMsIGFscGhhPTAuNSkgKyAKICBzY2FsZV9jb2xvcl9ncmFkaWVudCgnMCcsIGxvdyA9ICIjRkZGRkZGMDAiLCBoaWdoID0gIiM2ZGMwYTYiKSArCiAgbmV3X3NjYWxlKCJjb2xvciIpICsKICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtYmVkZGluZ1tlbWJlZGRpbmckYDJgPjAuMSxdLCAKICAgICAgICAgICAgIGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yLCBjb2xvciA9IGAyYCksc2hhcGU9MTYsIHNpemUgPSAzLCBhbHBoYT0wLjUpICsgCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQoJzEnLCBsb3cgPSAiI0ZGRkZGRjAwIiwgaGlnaCA9ICIjZTJiMzk4IikgKwogICBuZXdfc2NhbGUoImNvbG9yIikgKwogICAgZ2VvbV9wb2ludChkYXRhID0gZW1iZWRkaW5nW2VtYmVkZGluZyRgM2A+MC4xLF0sIAogICAgICAgICAgICAgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIsIGNvbG9yID0gYDNgKSxzaGFwZT0xNiwgc2l6ZSA9IDMsIGFscGhhPTAuNSkgKyAKICBzY2FsZV9jb2xvcl9ncmFkaWVudCgnMicsIGxvdyA9ICIjRkZGRkZGMDAiLCBoaWdoID0gIiNlMmEyY2EiKSArCiAgbmV3X3NjYWxlKCJjb2xvciIpICsKICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtYmVkZGluZ1tlbWJlZGRpbmckYDRgPjAuMSxdLCAKICAgICAgICAgICAgIGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yLCBjb2xvciA9IGA0YCksc2hhcGU9MTYsIHNpemUgPSAzLCBhbHBoYT0wLjUpICsgCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQoJzMnLCBsb3cgPSAiI0ZGRkZGRjAwIiwgaGlnaCA9ICIjZDFlYmE4IikgKwogICAgICAgIHhsYWIoIlVNQVAgMSIpICsgeWxhYigiVU1BUCAyIikgICsKICAgICAgICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMiwgImNtIikpKSkgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpICsgCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCmdnc2F2ZSgiLi9maWcyL3N1cF9kczJBQ191bWFwLnBuZyIsZGV2aWNlID0gcG5nLCBwbG90ID0gZ2dvYmosaGVpZ2h0ID0gMTAsd2lkdGggPSAxMCkKYGBgCgoKIyBHU1ZBCmBgYHtyfQpHU1ZBcmVzIDwtIHJlYWRSRFMoIkdTVkFyZXMucmRzIikKZXMgPC0gZGF0YS5mcmFtZSh0KEdTVkFyZXMpLHN0cmluZ3NBc0ZhY3RvcnM9RikgICPlj6/op4bljJbnm7jlhbPpgJrot6/nmoTlnKh1bWFw5LiK6IGa6ZuG5oOF5Ya1CmRzMl9BQyA8LSBBZGRNZXRhRGF0YShkczJfQUMsIGVzKQpmKCJDVUlfVENGMjFfVEFSR0VUU19VUCIsIGxhYmVsID0gRiwgZHMyX0FDKSArc2NhbGVfY29sb3VyX2dyYWRpZW50KGxvdz0iIzFFOTBGRiIsIGhpZ2g9IiNmZjIxMjEiKQoKZHMyX1BBIDwtIEFkZE1ldGFEYXRhKGRzMl9QQSwgZXMpCmYoIkNVSV9UQ0YyMV9UQVJHRVRTX1VQIiwgbGFiZWwgPSBGLCBkczJfUEEpICtzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93PSIjMUU5MEZGIiwgaGlnaD0iI2ZmMjEyMSIpCmBgYAoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLgoKV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuCgpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuCg==